﻿using System.Collections.Generic;
using System.ComponentModel;

namespace CulvertDesignerWPF
{
    public class CulvertItem : INotifyPropertyChanged
    {
        private string _name;
        private string _dia;
        private string _nob;
        private string _q;
        private string _manningn;
        private string _s0;
        private string _du,_vc,_vu,_fn,_dc, _cap;
        private bool isUpdated;

        public CulvertItem()
        {
            _dia = string.Empty;
            NumBarrel = "1";
            ManningN = "0.014";
            Q25 = "1.0";
            S0= "0.01";
            IsUpdated = false;
        }
        public bool IsUpdated
        {
            get => isUpdated;
            set
            {
                if (isUpdated != value)
                {
                    isUpdated = value;
                    OnPropertyChanged(nameof(IsUpdated));
                }
            }
        }
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
            }
        }

        public List<string> Parameter1Options { get; set; } = new List<string> { "600", "800", "1000", "1200" };

        public string Diameter
        {
            get { return _dia; }
            set
            {
                _dia = value;
                IsUpdated = false;
                OnPropertyChanged(nameof(Diameter));
            }
        }

        public string ManningN
        {
            get { return _manningn; }
            set
            {
                if (IsValidPositiveDouble(value))
                {
                    _manningn = value;
                    IsUpdated = false;
                }
                else
                {
                    _manningn = "Invalid";
                }
                OnPropertyChanged(nameof(ManningN));
                // UpdateParameter8();
            }
        }

        public string NumBarrel
        {
            get { return _nob; }
            set
            {
                if (IsValidPositiveInteger(value))
                {
                    _nob = value;
                    IsUpdated = false;
                }
                else
                {
                    _nob = "Invalid";
                }
                OnPropertyChanged(nameof(NumBarrel));
                // UpdateParameter8();
            }
        }

        public string Q25
        {
            get { return _q; }
            set
            {
                if (IsValidPositiveDouble(value))
                {
                    _q = value;
                    IsUpdated = false;
                }
                else
                {
                    _q = "Invalid";
                }
                OnPropertyChanged(nameof(Q25));
                // UpdateParameter8();

            }
        }

        public string Qd
        {
            get { return string.Format("{0:F3}", double.Parse(_q)/int.Parse(_nob)); }
        }

        public string S0
        {
            get { return _s0; }
            set
            {
                if (IsValidPositiveDouble(value))
                {
                    _s0 = value;
                    IsUpdated = false;
                }
                else
                {
                    _s0 = "Invalid";
                }
                OnPropertyChanged(nameof(S0));
                // UpdateParameter8();

            }
        }

        public string UniformDepth
        {
            get { return _du; }
            private set
            {
                _du = value;
                OnPropertyChanged(nameof(UniformDepth));
            }
        }
        public string CapacityDis
        {
            get { return _cap; }
            private set
            {
                _cap = value;
                OnPropertyChanged(nameof(CapacityDis));
            }
        }
        public string FroudeNum
        {
            get { return _fn; }
            private set
            {
                _fn = value;
                OnPropertyChanged(nameof(FroudeNum));
            }
        }
        public string UniformVelo
        {
            get { return _vu; }
            private set
            {
                _vu = value;
                OnPropertyChanged(nameof(UniformVelo));
            }
        }
        public string CriticalVelo
        {
            get { return _vc; }
            private set
            {
                _vc = value;
                OnPropertyChanged(nameof(CriticalVelo));
            }
        }
        public string CriticalDepth
        {
            get { return _dc; }
            private set
            {
                _dc = value;
                OnPropertyChanged(nameof(CriticalDepth));
            }
        }
        public void UpdateParameter8()
        {
            // Parse parameters as numbers and sum them up
            if (double.TryParse(Diameter, out double d) && 
                double.TryParse(NumBarrel, out double nb)  &&
                double.TryParse(Q25, out double flow) &&
                double.TryParse(S0, out double s0) &&
                double.TryParse(ManningN, out double n)
                )
            {
                var du = CulvertCalculator.CalculateUniformDepth(flow,d/1000,s0,n);
                var vu = flow / CulvertCalculator.CalculateAreaByDepth(du, d / 1000);
                double cap = CulvertCalculator.CalculateCapacity(d / 1000, s0, n).Item1;
                var dc = CulvertCalculator.CalculateCriticalDepth(flow,d / 1000);
                var vc = CulvertCalculator.CalculateCriticalVelocity(flow,d / 1000);
                var fn=CulvertCalculator.CalculateFroudeNumber(flow,d / 1000,s0,n);
                OnPropertyChanged(nameof(Qd));
                UniformDepth = string.Format("{0:F1}", du);
                UniformVelo = string.Format("{0:F3}", vu);
                CriticalVelo = string.Format("{0:F3}", vc);
                CriticalDepth = string.Format("{0:F1}", dc);
                CapacityDis = string.Format("{0:F3}", cap);
                FroudeNum = string.Format("{0:F3}", fn);
                IsUpdated = true;
            }
            else
            {
                UniformDepth = "Invalid";
                IsUpdated = false;
            }
            OnPropertyChanged(nameof(UniformDepth));
        }

        // Implementation of INotifyPropertyChanged interface
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private bool IsValidPositiveInteger(string value)
        {
            return int.TryParse(value, out int result) && result > 0;
        }
        private bool IsValidPositiveDouble(string value)
        {
            return double.TryParse(value, out double result) && result > 0;
        }

    }
}
